// ============================================
// 06 - 结构体 (Structs)
// ============================================

/// 结构体是一种自定义数据类型，允许命名和包装多个相关的值

// ==================== 定义结构体 ====================

/// 基本结构体定义
#[derive(Debug)] // 允许使用 {:?} 打印结构体
struct User {
    username: String,
    email: String,
    sign_in_count: u64,
    active: bool,
}

pub fn defining_structs() {
    println!("\n=== 定义结构体 ===");
    
    // 创建结构体实例
    let user1 = User {
        email: String::from("someone@example.com"),
        username: String::from("someusername123"),
        active: true,
        sign_in_count: 1,
    };
    
    println!("用户名: {}", user1.username);
    println!("邮箱: {}", user1.email);
    println!("登录次数: {}", user1.sign_in_count);
    println!("激活状态: {}", user1.active);
}

/// 可变结构体
pub fn mutable_structs() {
    println!("\n=== 可变结构体 ===");
    
    let mut user1 = User {
        email: String::from("someone@example.com"),
        username: String::from("someusername123"),
        active: true,
        sign_in_count: 1,
    };
    
    println!("原始邮箱: {}", user1.email);
    
    // 修改字段值
    user1.email = String::from("anotheremail@example.com");
    println!("修改后邮箱: {}", user1.email);
    
    // 注意: 整个实例必须是可变的，不能单独某个字段可变
}

/// 使用函数创建结构体
pub fn build_user(email: String, username: String) -> User {
    User {
        email,    // 字段初始化简写
        username, // 当参数名与字段名相同时
        active: true,
        sign_in_count: 1,
    }
}

pub fn struct_functions() {
    println!("\n=== 使用函数创建结构体 ===");
    
    let user = build_user(
        String::from("user@example.com"),
        String::from("username"),
    );
    
    println!("创建的用户: {:?}", user);
}

/// 结构体更新语法
pub fn struct_update_syntax() {
    println!("\n=== 结构体更新语法 ===");
    
    let user1 = User {
        email: String::from("someone@example.com"),
        username: String::from("someusername123"),
        active: true,
        sign_in_count: 1,
    };
    
    // 使用结构体更新语法创建新实例
    let user2 = User {
        email: String::from("another@example.com"),
        ..user1 // 其余字段从 user1 获取
    };
    
    println!("user2 邮箱: {}", user2.email);
    println!("user2 用户名: {}", user2.username);
    
    // 注意: user1 中的 String 字段被移动了
    // println!("{}", user1.username); // ❌ 错误: 值已被移动
    println!("active 和 sign_in_count 实现了 Copy，user1 的这些字段仍可用:");
    println!("user1.active: {}", user1.active);
}

// ==================== 元组结构体 ====================

/// 元组结构体
/// 类似元组的结构体，字段没有名称
#[derive(Debug)]
struct Color(i32, i32, i32);

#[derive(Debug)]
struct Point(i32, i32, i32);

pub fn tuple_structs() {
    println!("\n=== 元组结构体 ===");
    
    let black = Color(0, 0, 0);
    let origin = Point(0, 0, 0);
    
    println!("颜色: {:?}", black);
    println!("坐标: {:?}", origin);
    
    // 访问元组结构体的字段
    println!("颜色的红色分量: {}", black.0);
    println!("坐标的 x: {}", origin.0);
    
    // 注意: Color 和 Point 是不同的类型
    // let confusion = add_colors(black, origin); // ❌ 类型不匹配
}

// ==================== 类单元结构体 ====================

/// 类单元结构体
/// 没有任何字段的结构体
struct AlwaysEqual;

pub fn unit_like_structs() {
    println!("\n=== 类单元结构体 ===");
    
    let subject = AlwaysEqual;
    println!("类单元结构体常用于实现 trait");
    
    // 用于没有数据但需要类型的场景
    let _another = AlwaysEqual;
}

// ==================== 方法 ====================

/// 为结构体定义方法
#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    // 方法 - 第一个参数是 self
    fn area(&self) -> u32 {
        self.width * self.height
    }
    
    // 方法可以获取所有权
    fn _consume(self) {
        // self 被移动
    }
    
    // 方法可以可变借用
    fn scale(&mut self, factor: u32) {
        self.width *= factor;
        self.height *= factor;
    }
    
    // 方法可以有多个参数
    fn can_hold(&self, other: &Rectangle) -> bool {
        self.width > other.width && self.height > other.height
    }
}

pub fn methods() {
    println!("\n=== 方法 ===");
    
    let rect = Rectangle {
        width: 30,
        height: 50,
    };
    
    println!("矩形: {:?}", rect);
    println!("面积: {}", rect.area());
    
    let rect2 = Rectangle {
        width: 10,
        height: 40,
    };
    let rect3 = Rectangle {
        width: 60,
        height: 45,
    };
    
    println!("rect 能容纳 rect2 吗? {}", rect.can_hold(&rect2));
    println!("rect 能容纳 rect3 吗? {}", rect.can_hold(&rect3));
}

pub fn mutable_methods() {
    println!("\n=== 可变方法 ===");
    
    let mut rect = Rectangle {
        width: 10,
        height: 20,
    };
    
    println!("缩放前: {:?}", rect);
    rect.scale(2);
    println!("缩放后: {:?}", rect);
}

// ==================== 关联函数 ====================

impl Rectangle {
    // 关联函数 - 不使用 self
    fn square(size: u32) -> Rectangle {
        Rectangle {
            width: size,
            height: size,
        }
    }
    
    // 另一个关联函数
    fn new(width: u32, height: u32) -> Rectangle {
        Rectangle { width, height }
    }
}

pub fn associated_functions() {
    println!("\n=== 关联函数 ===");
    
    // 使用 :: 调用关联函数
    let square = Rectangle::square(25);
    println!("正方形: {:?}", square);
    println!("正方形面积: {}", square.area());
    
    let rect = Rectangle::new(30, 40);
    println!("矩形: {:?}", rect);
}

// ==================== 多个 impl 块 ====================

impl Rectangle {
    fn perimeter(&self) -> u32 {
        2 * (self.width + self.height)
    }
}

pub fn multiple_impl_blocks() {
    println!("\n=== 多个 impl 块 ===");
    
    let rect = Rectangle {
        width: 30,
        height: 50,
    };
    
    println!("周长: {}", rect.perimeter());
    println!("可以有多个 impl 块，但通常没必要");
}

// ==================== 实际应用示例 ====================

/// 书籍结构体
#[derive(Debug)]
struct Book {
    title: String,
    author: String,
    pages: u32,
    available: bool,
}

impl Book {
    fn new(title: String, author: String, pages: u32) -> Book {
        Book {
            title,
            author,
            pages,
            available: true,
        }
    }
    
    fn borrow(&mut self) -> bool {
        if self.available {
            self.available = false;
            true
        } else {
            false
        }
    }
    
    fn return_book(&mut self) {
        self.available = true;
    }
    
    fn info(&self) -> String {
        format!(
            "《{}》- {} ({} 页) [{}]",
            self.title,
            self.author,
            self.pages,
            if self.available { "可借" } else { "已借出" }
        )
    }
}

pub fn practical_example() {
    println!("\n=== 实际应用: 图书管理 ===");
    
    let mut book = Book::new(
        String::from("Rust 编程语言"),
        String::from("Steve Klabnik"),
        500,
    );
    
    println!("{}", book.info());
    
    if book.borrow() {
        println!("借阅成功");
    }
    println!("{}", book.info());
    
    book.return_book();
    println!("归还后: {}", book.info());
}

/// 圆形结构体
#[derive(Debug)]
struct Circle {
    center: Point2D,
    radius: f64,
}

#[derive(Debug, Clone, Copy)]
struct Point2D {
    x: f64,
    y: f64,
}

impl Circle {
    fn new(x: f64, y: f64, radius: f64) -> Circle {
        Circle {
            center: Point2D { x, y },
            radius,
        }
    }
    
    fn area(&self) -> f64 {
        std::f64::consts::PI * self.radius * self.radius
    }
    
    fn circumference(&self) -> f64 {
        2.0 * std::f64::consts::PI * self.radius
    }
}

pub fn nested_structs() {
    println!("\n=== 嵌套结构体 ===");
    
    let circle = Circle::new(0.0, 0.0, 5.0);
    println!("圆形: {:?}", circle);
    println!("面积: {:.2}", circle.area());
    println!("周长: {:.2}", circle.circumference());
}

/// 主函数 - 演示所有功能
#[allow(dead_code)]
pub fn main() {
    println!("╔════════════════════════════════════════╗");
    println!("║   Rust 结构体教程                      ║");
    println!("╚════════════════════════════════════════╝");
    
    defining_structs();
    mutable_structs();
    struct_functions();
    struct_update_syntax();
    tuple_structs();
    unit_like_structs();
    methods();
    mutable_methods();
    associated_functions();
    multiple_impl_blocks();
    practical_example();
    nested_structs();
    
    println!("\n✅ 结构体教程完成！");
}

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_rectangle_area() {
        let rect = Rectangle { width: 30, height: 50 };
        assert_eq!(rect.area(), 1500);
    }
    
    #[test]
    fn test_rectangle_can_hold() {
        let rect1 = Rectangle { width: 30, height: 50 };
        let rect2 = Rectangle { width: 10, height: 40 };
        assert!(rect1.can_hold(&rect2));
    }
    
    #[test]
    fn test_square() {
        let square = Rectangle::square(25);
        assert_eq!(square.width, 25);
        assert_eq!(square.height, 25);
    }
    
    #[test]
    fn test_book_borrow() {
        let mut book = Book::new(
            String::from("Test"),
            String::from("Author"),
            100,
        );
        assert!(book.available);
        assert!(book.borrow());
        assert!(!book.available);
    }
}

